using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Reflection;
using App.Modelo.Interfaces;
using App.Persistencia;
using System.Diagnostics;
using System.IO;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlServer.Management.Common;

using App.Modelo.Config;

namespace App.Instalador
{
    public class Instalador
    {
        private const string PreInstallSql = "sql/audit-pre-install.sql sql/solinf-pre-install.sql";
        private const string PostInstallSql = "sql/audit-post-install.sql sql/solinf-post-install.sql";

        private Repositorio _repositorio;

        public void Run()
        {
            _repositorio = new Repositorio();

            _repositorio.OpenSession();

            PreInstall();

            borrarBase();
            crearBase();

            PostInstall();

            string[] permisos = getACL();

            var ins = new SolInfInstaladorDatos();

            Console.WriteLine("Instalando datos seguridad");

            ins.InstalarDatosSeguridad(_repositorio, permisos);

            Console.WriteLine("Populando datos de prueba");

            ins.InstalarDatosDemo(_repositorio);

            Console.WriteLine("Listo");

            _repositorio.CloseSession();

            Console.WriteLine("Presione enter para continuar");
            Console.ReadLine();
        }

        private void PreInstall()
        {


            foreach (var postInstall in PreInstallSql.Split(' '))
            {
                if (!File.Exists(postInstall))
                    return;

                runSql(postInstall);
            }
        }

        private void PostInstall()
        {


            foreach (var postInstall in PostInstallSql.Split(' '))
            {
                if (!File.Exists(postInstall))
                    return;

                runSql(postInstall);
            }
        }


        private void runSql(string fileName)
        {
            string sqlConnectionString = _repositorio.Connection.ConnectionString;
            var conn = new SqlConnection(sqlConnectionString);
            conn.Open();


            var file = new FileInfo(fileName);
            var reader = file.OpenText();
            var script = reader.ReadToEnd();

            var server = new Server(new ServerConnection(conn));

            server.ConnectionContext.ExecuteNonQuery(script);
        }


        private void p_ErrorDataReceived(object sender, DataReceivedEventArgs e)
        {
            Console.WriteLine(e.Data);
        }

        private void p_Exited(object sender, EventArgs e)
        {
            Console.WriteLine("Exit");
        }

        private void p_OutputDataReceived(object sender, DataReceivedEventArgs e)
        {
            Console.Write(e.Data);
        }

        private string[] getACL()
        {
            SeguridadConfiguration cfg = SeguridadConfiguration.GetConfig();
            var list = new List<Assembly>();

            list.Add(Assembly.GetAssembly(typeof (SeguridadConfiguration)));

            foreach (ModuloSettingElements m in cfg.Modulos)
            {
                list.Add(Assembly.Load(m.AssemblyName));
            }

            List<string> privilegios = new List<string>();

            foreach (Assembly assembly in list)
            {
                Console.WriteLine("Agregando seguridad: " + assembly.FullName);
                foreach (var formulario in assembly.GetTypes())
                {
                    foreach (IFormulario formAttr in
                        formulario.GetCustomAttributes(typeof (IFormulario), true))
                    {
                        foreach (var funcion in formulario.GetMethods())
                        {
                            foreach (IFuncion funcAttr
                                in funcion.GetCustomAttributes(typeof (IFuncion), true))
                            {
                                privilegios.Add(formAttr.Nombre + "/" + funcAttr.Nombre);
                            }
                        }
                    }
                }
            }
            return privilegios.ToArray();
        }

        private void borrarBase()
        {
            Console.Write("Borrando base actual ");
            DataBaseUtils.BorrarBase();
            Console.WriteLine("Listo");
        }

        private void crearBase()
        {
            Console.Write("Creando base nueva ");
            DataBaseUtils.CrearBase();
            Console.WriteLine("Listo");
        }
    }
}